package com.curd.mp.base.service.impl;

import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.curd.common.config.exception.CloudException;
import com.curd.mp.base.service.IBaseService;
import org.springframework.util.Assert;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.IOException;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.util.List;

public class IBaseAbstractService<DOMAIN, ID, M extends BaseMapper<DOMAIN>> extends ServiceImpl<M, DOMAIN> implements IBaseService<DOMAIN, ID> {
    /**
     * 动态 IOC代理
     *
     * 多个需要使用 Autowired
     */
    @Resource
    protected M mapper;


    /**
     * 当前泛型真实类型的Class
     */
    private Class<DOMAIN> modelClass;

    public IBaseAbstractService() {
        ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass();
        modelClass = (Class<DOMAIN>) pt.getActualTypeArguments()[0];
    }

    /**
     * 通过excel导入数据
     *
     * @return
     */
    @Override
    public String importExcel(Class<DOMAIN> clazz, MultipartFile file) {
        /**
         * INSTER 使用哪种方法保存 1 为遍历保存
         */
        int count = 0, INSTER = 1;
        long time = 0;
        try {
            long start = System.currentTimeMillis();
            ExcelReader reader = ExcelUtil.getReader(file.getInputStream());
            List<DOMAIN> all = reader.readAll(clazz);
            //保存
            switch (INSTER){
                case 0:
                default:
                    /**
                     * 批量保存
                     * TODO
                     * 请注意 ： 该批量保存接口测试失败  暂无法使用 原因未知
                     */
                    count = super.saveBatch(all, all.size()) ? all.size() : 0;
                    break;
                case 1:
                    /**
                     * 遍历保存 每次保存完后的到是否保存成功的状态 可以依此计数
                     */
                    for(DOMAIN domain : all){
                        count += super.save(domain) ? 1 : 0;
                    }
            }

            time = System.currentTimeMillis() - start;
        } catch (Exception e) {
            log.error("录入失败" + e);
            throw new CloudException("录入失败");
        }finally {
            try {
                file.getInputStream().close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if (INSTER ==1 ){
            return "录入统计: " + count + " 条数据，耗时 " + time + " ms";
        }
        return "录入统计: " + count + " 条数据，耗时 " + time + " ms" +
                "\n提示：Mp自身的批量保存并没有提供获取保存成功数量的方法，这里的成功数量实际为从数据源读取到的有效数据量";
    }

    /**
     * ID为当前操作者的ID，即操作者身份
     * 它将与某个值（如登陆后的token，session等中的身份）比对验证
     *
     * @param userCheckId
     * @param msg
     */
    @Override
    public void checkUser(ID userCheckId, String msg) {
        /**
         * 这里只是做了一个测试性的身份验证
         */
        System.out.println("\n预留接口>>>>>>>>>>>>>>>>>>>>>>>>>>>>这里仅供测试验证，具体验证请自行根据需求而定>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>测试验证开始");
        Assert.isTrue("12345".equals(String.valueOf(userCheckId)), "身份效验失败");
        System.out.println("预留接口>>>效验用户权限 操作用户：" + userCheckId + "验证通过-------- 预留接口 效验逻辑请自按需添加");
        System.out.println("预留接口>>>>>>>>>>>>>>>>>>>>>>>>>>>>这里仅供测试验证，具体验证请自行根据需求而定>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>测试验证结束\n");
    }

    @Override
    public int removeAll() {
        int count = 0;
        try {
            Field field = modelClass.getDeclaredField("id");
            field.setAccessible(true);
            for (DOMAIN domain : super.list()){
                count += super.removeById((Serializable) field.get(domain)) ? 1 : 0;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return count;
    }
}
